/* TA-LIB Copyright (c) 1999-2006, Mario Fortier
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or
 * without modification, are permitted provided that the following
 * conditions are met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in
 *   the documentation and/or other materials provided with the
 *   distribution.
 *
 * - Neither name of author nor the names of its contributors
 *   may be used to endorse or promote products derived from this
 *   software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/* List of contributors:
 *
 *  Initial  Name/description
 *  -------------------------------------------------------------------
 *  BT       Barry Tsung
 *
 * Change history:
 *
 *  MMDDYY BY    Description
 *  -------------------------------------------------------------------
 *  012706 BT    First version.
 */

/* Description:
 *       Do formating of Java source code files.
 */

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;

public class PrettyCode {
   int line;
   int level;
   BufferedReader in;
   PrintWriter    out;
   
   String indentString = "   ";
   
   boolean insideOfComment;
   
   boolean unfinishedStatement;
   
   String lineBuffer;
   
   public PrettyCode(String inFileName, String outFileName) throws FileNotFoundException{
      this.in  = new BufferedReader(new FileReader(inFileName));
      this.out = new PrintWriter(outFileName);
   }
   
   public PrettyCode process() throws IOException{
      while( (lineBuffer=in.readLine())!=null ){
         processLine(lineBuffer);
         out.println();
         line++;
      }
      out.flush();
      return this;
   }
   
   public PrettyCode close() throws IOException{
      in.close();
      out.close();
      return this;
   }
   
   void processLine(String buffer){
      if( level > 0 ){
         buffer=buffer.trim();
      }
      if( insideOfComment ){
         appendIndents("");
         buffer = processComment(buffer);
         while((buffer=processBuffer(buffer))!=null);
      }else{
         appendIndents(buffer);
         while((buffer=processBuffer(buffer))!=null);
      }
   }
   
   String processBuffer(String buffer){
      if( buffer == null ){ return null; }
      if( buffer.startsWith("/*")){
         if( insideOfComment ){
            error("comment inside of comment");
         }
         insideOfComment=true;
         out.print(buffer.substring(0,2));
         buffer=processComment(substring(buffer,2));
      }else if(buffer.startsWith( "//")){
         out.print(buffer);
      }else if(buffer.startsWith("\"")){
         unfinishedStatement=true;
         int i=buffer.indexOf("\"");
         if( i == -1 ){
            error("no matching ending \"");
         }else{
            out.print(buffer.substring(0,i+1));
            return buffer.substring(i+1);
         }         
      }else{
         for(int i=0;i<buffer.length();i++){
            char c = buffer.charAt(i);
            char cc = (i == (buffer.length()-1))? 0:buffer.charAt(i+1);            
            if( c == '{' ){
               unfinishedStatement=false;
               level++;
               out.print(buffer.substring(0, i+1));
               return substring(buffer, i+1);
            }else if( c == '}' ){
               unfinishedStatement=false;
               level--;
               out.print(buffer.substring(0, i+1));
               return substring(buffer, i+1);         
            }else if( c == '"'){
               out.print(buffer.substring(0, i));
               return substring(buffer, i);
            }else if( c == '/' && cc == '/' ){
               out.print(buffer);
               return null;
            }else if( c == '/' && cc == '*' ){
               out.print(buffer.substring(0, i));
               return substring(buffer, i);
            }else if( c == ' ' ){
               
            }else if( c == ';' ){
               unfinishedStatement=false;
            }else if( c == ')' && cc == ',' ){
               unfinishedStatement=false;
               i++;
            }else{
               unfinishedStatement=true;
            }
         }
         out.print(buffer);
      }
      return null;
   }

   String processComment(String buf){
      int i=buf.indexOf("*/");
      if( i == -1 ){
         out.print(buf);
      }else{
         insideOfComment=false;
         out.print(buf.substring(0,i+2));
         return substring(buf, i+2);
      }
      return null;
   }
   
   void appendIndents(String buf){
      int n=level;
      if( unfinishedStatement ){
         if(!buf.startsWith("{")){
            n++;
         }
      }
      if( buf.startsWith("}") ){
         n--;
      }
      for(int i=0;i<n;i++){ out.print(indentString); }
   }
   
   void error(String msg){
      System.err.println("ERROR one line ["+line+"] : "+msg);
   }
   
   String substring(String s, int i){
      if( i>(s.length()-1)){return "";}
      return s.substring(i);
   }
   
   public static boolean verify(String fileName1, String fileName2) throws IOException{
      BufferedReader f1 = new BufferedReader(new FileReader(fileName1));
      BufferedReader f2 = new BufferedReader(new FileReader(fileName2));
      int line=0;
      String buf1, buf2;
      while((buf1=f1.readLine())!= null){
         if((buf2=f2.readLine())==null){
            System.err.println(fileName2+" is shorter than "+fileName1);
            return false;
         }
         if( !buf1.trim().equals(buf2.trim()) ){
            System.err.println("Error on line "+line);
            System.err.println(fileName1+"='"+buf1+"'");
            System.err.println(fileName2+"='"+buf2+"'");
            return false;
         }
         line++;
      }
      if( (buf2 = f2.readLine()) != null ){
         System.err.println(fileName1+" is shorter than "+fileName2);
         return false;         
      }
      return true;
   }   
}

